#ifndef xpack_docker_bits_array
#define xpack_docker_bits_array
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::utils_bits_array::inc
#include"adapter/random_access.hpp"
#include"define/base_type.hpp"
#include"macro/xstruct.hpp"
#include"memop/fill.hpp"
#include"memop/zeros.hpp"
#include"math/index_system.hpp"
#include"meta/fit_bits.hpp"
#pragma pop_macro("xuser")

namespace mixc::utils_bits_array{
    template<uxx bits_v>
    xstruct(
        xtmpl(bits_item, bits_v),
        xprif(m_bits, u08p),
        xprif(m_mask, u08)
    )
    private:
        using fit_bit_t = inc::fit_bits<bits_v>;
    public:
        constexpr bits_item(the_t const &) = default;
        constexpr bits_item(u08p bits, u08 mask) : 
            m_bits(bits), m_mask(mask){
        }

        the_t & operator=(the_t const & value){
            for(uxx i = 0; i < bits_v; i++){
                m_bits[i] = value.m_bits[i] & m_mask ? m_bits[i] | m_mask : m_bits[i] & ~m_mask;
            }
            return *this;
        }

        the_t & operator=(fit_bit_t value){
            for(uxx i = 0; i < bits_v; i++){
                m_bits[i]   = value & 1 ? m_bits[i] | m_mask : m_bits[i] & ~m_mask;
                value     >>= 1;
            }
            return *this;
        }

        operator fit_bit_t() const {
            fit_bit_t value = 0;
            for(uxx i = bits_v; i--;){
                value <<= 1;
                value  |= m_mask & m_bits[i] ? 1 : 0;
            }
            return value;
        }

        void swap_value(the_t value){
            fit_bit_t a = xthe;
            fit_bit_t b = value;
            xthe        = b;
            value       = a;
        }
    $

    
    template<uxx length_v, uxx bits_per_item_v = 1>
    xstruct(
        xtmpl(bits_array, length_v, bits_per_item_v),
        xpubb(
            inc::random_access<
                bits_array<length_v, bits_per_item_v>, bits_item<bits_per_item_v>
            >
        ),
        xprif(m_items, u08[length_v / xbitsof(u08) + (length_v % xbitsof(u08) != 0)][bits_per_item_v])
    )
    public:
        using final_t       = the_t;
        using item_wraper_t = bits_item<bits_per_item_v>;
        using fit_bits      = inc::fit_bits<bits_per_item_v>;
    public:
        xprops()
            /* 属性：当前维度数组元素的个数 */
            xpubgetx(length, uxx){
                xr{ return length_v; }
            };

            xpubgetx(bits_per_item, uxx){
                xr{ return bits_per_item_v; }
            };

            xpubgetx(is_all_zero, bool){
                xr{
                    for(uxx i = 0, length = xthe->length; i < length; i++){
                        for(uxx j = 0; j < bits_per_item_v; j++){
                            if (xthe.m_items[i][j] != 0){
                                return false;
                            }
                        }
                    }
                    return true;
                }
            };
        $

        xprops_operator()

    public:
        constexpr bits_array(bits_array const &) = default;
        constexpr bits_array() :
            m_items{}{
        }

        void reset_all(){
            inc::zeros(m_items, sizeof(m_items));
        }

        void set_all(){
            inc::fill(m_items, u08(0xff), sizeof(m_items));
        }

        void set_all(auto && value){
            for(uxx i = 0; i < length_v; i++){
                this->random_get(i) = value;
            }
        }

        template<inc::can_interval interval_t>
        void reset_range(interval_t const & range){
            this->set_range(range, 0);
        }

        template<inc::can_interval interval_t>
        void set_range(interval_t const & range){
            this->set_range(range, 1);
        }

        template<inc::can_interval interval_t>
        bstate_t set_range(interval_t const & range, auto && value){
            if (range.normalize(xthe->length) == bstate_t::fail){
                return bstate_t::fail;
            }

            for(uxx i = range->left, end = range->right; i <= end; i++){
                this->random_get(i) = fit_bits(value);
            }
            return bstate_t::success;
        }

    private:
        friend inc::random_access<the_t, item_wraper_t>;

        item_wraper_t random_get(uxx index) const {
            item_wraper_t bits(m_items[index >> 3], u08(1 << (index & 0x7)));
            return bits;
        }
    $
}

namespace mixc::utils_bits_array::origin{
    using mixc::utils_bits_array::bits_array;
}

#endif

xexport_space(mixc::utils_bits_array::origin)
